\documentclass{ctexart}
\bibliographystyle{IEEEtran}
\usepackage{booktabs}
\usepackage{url}
\usepackage{algorithm,algorithmic}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{tikz}
\pagestyle{plain}
\title{五则计算器}
\author{张祺\\信息与计算科学 2101  3210104145}
\date{2023年1月1日}
\begin{document}
\maketitle
\section{设计思路}
由于输入是字符串，所以第一步肯定是将字符串中的浮点数和运算符识别保存下来，而后将中缀表达式转换为后缀表达式，并以此进行数值计算。
\subsection{浮点数、运算符识别}
事先设置两个数组用以分别存放浮点数和运算符，并用Fnum记录下当前识别出并记录下的浮点数和运算符的总数。运算符部分我们只需要遍历整个字符串，当遇到\verb|"+-*/^（）"|时记录下即可;而在识别浮点数时，我们同样能轻松的识别出数字，但我们同时需记下该数字对应的位置和是否为小数部分，因此我定义了整形\verb|num_start|和\verb|num_point|来确定当前识别出的数字对应的位置。如果当前数字位于整数部分，则把num对应位置的数乘十加上当前数字，如果当前数字位于小数部分，则利用\verb|num_point|确定小数点后的位数然后加到num对应位置，最终num对应位置则是该浮点数的值。
\subsection{中缀转后缀}
读取到一个浮点数便将其记录在num[Fnum+1]位置上，而后将Fnum加一。读取到运算符，则将运算符与运算优先级绑定，并将运算优先级和栈顶元素优先级相比较，如果当前优先级大于栈顶优先级或栈为空栈，则入栈;如果当前优先级小于等于栈顶优先级则弹出栈顶元素对应运算符至str[Fnum+1]位置上，而后将Fnum加一，重复上述操作直到当前运算符入栈;特殊的，如果当前运算符是‘)’，则会让栈顶元素对应运算符不断弹出至str[Fnum+1]位置上，而后将Fnum加一，直到栈顶元素对应运算符为‘(’，此时再弹出一次但不存入str。当原字符串读取完毕时，弹出栈内的所有元素对应的运算符。此时以字符数字对应位置是否为\verb|‘\0’|为区分，如果为\verb|‘\0’|则输出num[i]，如果不为\verb|‘\0’|则输出str[i]，输出的句子变为后缀表达式。
\subsection{数值计算}
有了后缀表达式，我们按顺序将碰到的浮点数依次入栈，如果遇到运算符，则先弹出栈顶元素为b，后弹出栈顶元素为a，按不同的运算符进行计算，而后将计算的结果result入栈，最后将后缀表达式遍历后，栈内应该只有一个元素，该元素便是运算的结果，输出即可。
\subsection{异常处理}
当有多处异常时，仅输出出现的第一处异常。
\subsubsection{括号不匹配}
当识别到‘)’时，会让栈顶元素不断弹出至找到‘('，如果到栈为空栈仍找不到’('，则flag为-1,输出“错误：括号不匹配”。而当原字符串读取完毕后，在弹出栈內的所有元素时发现了‘(',则flag也变为-1,输出“错误：括号不匹配”。
\subsubsection{除数为零}
在运算符为‘/’时，如果栈顶元素b为零，则flag为10,输出“错误：除数为零”。
\subsubsection{指数和底数均为零}
在运算符为\verb|‘^’|时，如果栈顶元素b和a均为零，则flag为20,输出“错误：指数和底数均为零”。
\subsubsection{表达式不符合规范}
如果原字符串连续出现两个运算符，或者在一个浮点数中出现两个小数点，flag为30,输出“错误：表达式不符合规范”。

\section{测试样例}
\subsection{$2^{(1+3)}$-5*(15.23)/(1+2)*3-5}
输出$2^{(1+3)}$-5*(15.23)/(1+2)*3-5 = -65.15
\subsection{1.25+(3*$(1+2^2)*3-43)^{(4-2)}$}
输出1.25+(3*$(1+2^2)*3-43)^{(4-2)}$ = 5.25
\subsection{$2^{(1+3))}$-5*(15.23)/(1+2)*3-5}
输出“错误：括号不匹配”
\subsection{$2^{(1+3)}$-5*(15.23)/(1-1)*3-5}
输出“错误：除数为零”
\subsection{$(2-2)^{(0+0)}$-5*(15.23)/(1+2)*3-5}
输出“错误：指数和底数均为零”
\subsection{1.25++(3*$(1+2^2)*3-43)^{(4-2)}$}
输出“错误：表达式不符合规范”
\subsection{1.2.5+(3*$(1+2^2)*3-43)^{(4-2)}$}
输出“错误：表达式不符合规范”
\end{document}
